package utils

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"fmt"
	"strconv"
	"time"

	// "io"
	"io/fs"
	"io/ioutil"
	"os"
	"sort"
	"strings"

	beego "github.com/beego/beego/v2/server/web"
)

type Filetile struct {
	Title   string
	Autor   string
	Content string
	Name    string
}

//存储文件
func SaveToFile(filename, filecontent string) error {
	var d1 = []byte(filecontent)
	if checkFileIsExist(filename) {

	} else {
		filename = GetCurrentPath() + filename
	}

	err := ioutil.WriteFile(filename, d1, 0666) //写入文件(字节数组)
	if err != nil {
		dr := strings.LastIndex(filename, "/")
		dir := filename[1:dr] + "/"
		err = os.MkdirAll(dir, 0777)
		err = ioutil.WriteFile(filename, d1, 0666)
		if err != nil {
			fmt.Println("savetofile two error:", err)
			return err
		}
		return nil
	} else {
		return nil
	}
}

//读取文件
func ReadFile(filename string) string {
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		fmt.Println("ReadFile error:", err)
		return ""
	} else {
		return string(bytes)
	}
}

//返回文件群内容标题等
func ReadFilesTile(filenames []string) []Filetile {
	//获取目录文件名
	postdir, _ := beego.AppConfig.String("postdir")
	postdir = GetCurrentPath() + postdir

	a := len(filenames)
	filetiles := make([]Filetile, a)

	for i, v := range filenames {
		title, autor, content := ReadFileTile(v)
		filetiles[i].Title = title
		filetiles[i].Autor = autor
		filetiles[i].Content = content

		//去除v包含的绝对路径
		v = strings.TrimPrefix(v, postdir)

		filetiles[i].Name = v
	}
	return filetiles
}

//读取文件并返回标题、时间+作者、内容
func ReadFileTile(filename string) (Title, Autor, Content string) {
	fi, err := os.Open(filename)
	if err != nil {
		fmt.Printf("Error: %s\n", err)
		return
	}
	defer fi.Close()
	// var con1 []string
	var buffer bytes.Buffer
	br := bufio.NewReader(fi)
	scanner := bufio.NewScanner(br)
	scanner.Split(bufio.ScanLines)
	i := 0
	for scanner.Scan() {
		i++
		switch i {
		case 1:
			Title = scanner.Text()
		case 2:
			Autor = scanner.Text()
		default:
			buffer.WriteString(scanner.Text())
		}
	}

	Content = buffer.String()

	return Title, Autor, Content
}

//排序sort所需
type ByModTime []fs.FileInfo

func (fil ByModTime) Len() int      { return len(fil) }
func (fil ByModTime) Swap(i, j int) { fil[i], fil[j] = fil[j], fil[i] }
func (fil ByModTime) Less(i, j int) bool {
	// return fil[i].ModTime().Before(fil[j].ModTime())
	return fil[i].ModTime().After(fil[j].ModTime())
}

//遍历目录,返回文件strings和目录
func ListDir(dir string) (files, dirs []string) {
	// timestamp := time.Now().Format("20060102.150405")
	var fileinfos []fs.FileInfo
	filedir := dir
	dirinfo, err := ioutil.ReadDir(filedir)
	if err != nil {
		fmt.Println("listdir error:", err)
	}
	for _, fileinfo := range dirinfo {
		if fileinfo.IsDir() {
			dirs = append(dirs, "/"+fileinfo.Name()+"/")
			filetmp, _ := ListDir(filedir + fileinfo.Name() + "/")
			for _, fileino := range filetmp {
				files = append(files, fileino)
			}
		} else {
			// files = append(files, filedir+fileinfo.Name())
			fileinfos = append(fileinfos, fileinfo)
		}

	}
	//对文件列表按时间排序
	sort.Sort(ByModTime(fileinfos))
	for _, fileinfo := range fileinfos {
		files = append(files, filedir+fileinfo.Name())
		// files = append(files, fileinfo.Name())
	}
	return files, dirs
}

//查找文件名,通过文件名和需要搜索的目录
func SearchFile(filedir, filename string) []fs.FileInfo {
	var fileinfos []fs.FileInfo
	dirinfo, err := ioutil.ReadDir(filedir)
	if err != nil {
		fmt.Println("listdir error:", err)
	}
	for _, fileinfo := range dirinfo {
		//判断是否为目录，如果是目录则进行目录搜索
		if fileinfo.IsDir() {
			// dirs = append(dirs, "/"+fileinfo.Name()+"/")
		} else {
			//判断是否包含文件名
			if strings.Contains(fileinfo.Name(), filename) {
				fileinfos = append(fileinfos, fileinfo)
			}
		}
	}
	return fileinfos
}

//归档文件，按传递目录，并写入model/archives.tpl
func ArchivesFile(dir string) bool {
	var fileinfos []fs.FileInfo
	var files, dirs []string
	filedir := dir
	dirinfo, err := ioutil.ReadDir(filedir)
	if err != nil {
		fmt.Println("listdir error:", err)
	}
	for _, fileinfo := range dirinfo {
		if fileinfo.IsDir() {
			dirs = append(dirs, "/"+fileinfo.Name()+"/")
			filetmp, _ := ListDir(filedir + fileinfo.Name() + "/")
			for _, fileino := range filetmp {
				files = append(files, fileino)
			}
		} else {
			fileinfos = append(fileinfos, fileinfo)
		}

	}
	//对文件列表按时间排序
	sort.Sort(ByModTime(fileinfos))

	//按年度时间进行分类，并形成文件内容
	var fileneirong string
	var t time.Time

	year, _, _ := time.Now().Date()

	fileneirong = fileneirong + strconv.Itoa(year) + "\n"

	for _, filetime := range fileinfos {
		t = filetime.ModTime()
		if t.Year() == year {
			fileneirong = fileneirong + filetime.Name() + "\n"
		} else {
			year = t.Year()
			fileneirong = fileneirong + strconv.Itoa(year) + filetime.Name() + "\n"
		}

	}

	//写入文件
	flneirongbyte := []byte(fileneirong)
	dir = GetCurrentPath() + "/static/archives/archives"
	err = ioutil.WriteFile(dir, flneirongbyte, 0777)
	if err != nil {
		fmt.Println(err)
		return false
	}
	return true
}

//int转换byte
func IntToBytes(n int) []byte {
	data := int64(n)
	bytebuf := bytes.NewBuffer([]byte{})
	binary.Write(bytebuf, binary.BigEndian, data)
	return bytebuf.Bytes()
}

//获取路径,获取当前运行的目录
func GetCurrentPath() string {
	dir, _ := os.Getwd()
	return dir
}

/**
 * 判断文件是否存在  存在返回 true 不存在返回false
 */
func checkFileIsExist(filename string) bool {
	var exist = true
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		exist = false
	}
	return exist
}

//删除文件
func RemoveFile(filename string) error {
	err := os.Remove(filename)
	if err != nil {
		return err
	}
	return nil
}
